/******************************************************************************

	COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2010.

	This file is part of the Maxsi Library.

	Maxsi Library is free software: you can redistribute it and/or modify it
	under the terms of the GNU Lesser General Public License as published by
	the Free Software Foundation, either version 3 of the License, or (at your
	option) any later version.

	Maxsi Library is distributed in the hope that it will be useful, but
	WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
	or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
	License for more details.

	You should have received a copy of the GNU Lesser General Public License
	along with Maxsi Library. If not, see <http://www.gnu.org/licenses/>.

	Maxsi Library
	A powerful Cross-Platform C++ General Purpose Library that allows you to
	efficiently create high-performance and reliable applications.

	MaxsiBufferStreamer.h
	A simple system for accessing a buffer or stream in a sync manner, where
	the source might not even be locally available, and may origin from another
	process, a file, a network socket, a virtual filesystem, or just a buffer
	in the process' address space.

******************************************************************************/

#ifndef MaxsiBufferStreamer_H
#define MaxsiBufferStreamer_H

BeginMaxsiNamespace

//=============================================================================
//	Forward declarations.
//=============================================================================
class IBufferStreamer;

//=============================================================================
//	Declare flags for this interface.
//=============================================================================
#define MAXSI_BUFFER_STREAMER_FLAG_READABLE (1<<0)
#define MAXSI_BUFFER_STREAMER_FLAG_WRITABLE (1<<1)
#define MAXSI_BUFFER_STREAMER_FLAG_RESIZABLE (1<<2)
#define MAXSI_BUFFER_STREAMER_FLAG_KNOWN_LENGTH (1<<3)
#define MAXSI_BUFFER_STREAMER_FLAG_SEEKABLE (1<<4)

//=============================================================================
//	Define where the IBufferStreamer interface is declared.
//=============================================================================
#undef MAXSI_INTERFACE
#define MAXSI_INTERFACE MAXSI_INTERFACE_ABSTRACT_BASECLASS

//=============================================================================
//	IBufferStreamer is an interface that allows all sorts of inputs in the same
//	manner, whether the input is a buffer, a network socket, a file, or perhaps
//	even the console input. The idea is that if you can construct a parser that
//	can use any instance of this interface as input, then you need not write
//	any other parses for any kind of input of this type.
//=============================================================================
MAXSI_CLASSLINK IBufferStreamer : public MaxsiInterface
{
	MAXSI_DECLARE_INTERFACE(IBufferStreamer);

public:
	virtual int GetFlags() MAXSI_INTERFACE;
	virtual FileSize_t GetSize() MAXSI_INTERFACE;
	virtual MaxsiError SetSize(FileSize_t NewSize) MAXSI_INTERFACE;
	virtual FileSize_t GetPosition() MAXSI_INTERFACE;
	virtual MaxsiError Seek(FileSize_t Offset) MAXSI_INTERFACE;
	virtual MaxsiError Read(BYTE* Destination, size_t DestinationSize, size_t* ActualRead) MAXSI_INTERFACE;
	virtual MaxsiError ReadFrom(FileSize_t Offset, BYTE* Destination, size_t DestinationSize, size_t* ActualRead) MAXSI_INTERFACE;
	virtual MaxsiError Write(BYTE* Source, size_t SourceSize) MAXSI_INTERFACE;
	virtual MaxsiError WriteTo(FileSize_t Offset, BYTE* Source, size_t SourceSize) MAXSI_INTERFACE;
	virtual MaxsiError WriteFlush() MAXSI_INTERFACE;

};

//=============================================================================
//	The follow implementations of the IBufferStreamer interface is implemented
//	in the Maxsi Library.
//=============================================================================
#undef MAXSI_INTERFACE
#define MAXSI_INTERFACE MAXSI_INTERFACE_IMPLEMENTED_IN_MAXSI_LIBRARY

//=============================================================================
//	MaxsiBufferStreamer is a simple way to access a buffer in our process space
//	just like if it was a file stream, which if a got a function that can use
//	a file stream, it now also just use actual buffers.
//=============================================================================
MAXSI_CLASSLINK MaxsiBufferStreamer : public IBufferStreamer
{
	MAXSI_DECLARE_IMPLEMENTATION(MaxsiBufferStreamer, IBufferStreamer, MAXSI_INTERFACE_DYNAMIC);

public:
	MaxsiBufferStreamer();
	~MaxsiBufferStreamer();

public:
	virtual int GetFlags() MAXSI_INTERFACE;
	virtual FileSize_t GetSize() MAXSI_INTERFACE;
	virtual MaxsiError SetSize(FileSize_t NewSize) MAXSI_INTERFACE;
	virtual FileSize_t GetPosition() MAXSI_INTERFACE;
	virtual MaxsiError Seek(FileSize_t Offset) MAXSI_INTERFACE;
	virtual MaxsiError Read(BYTE* Destination, size_t DestinationSize, size_t* ActualRead) MAXSI_INTERFACE;
	virtual MaxsiError ReadFrom(FileSize_t Offset, BYTE* Destination, size_t DestinationSize, size_t* ActualRead) MAXSI_INTERFACE;
	virtual MaxsiError Write(BYTE* Source, size_t SourceSize) MAXSI_INTERFACE;
	virtual MaxsiError WriteTo(FileSize_t Offset, BYTE* Source, size_t SourceSize) MAXSI_INTERFACE;
	virtual MaxsiError WriteFlush() MAXSI_INTERFACE;

public:
	BYTE* MyBuffer;
	size_t MyBufferUsed;
	size_t MyBufferSize;
	FileSize_t MyPosition;

public:
	void SetBuffer(BYTE* NewBuffer, size_t NewBufferSize, size_t NewBufferUsed);

};

//=============================================================================
//	MaxsiFileStreamer is a simple way to access a file through the
//	IBufferStreamer interface.
//=============================================================================
MAXSI_CLASSLINK MaxsiFileStreamer : public IBufferStreamer
{
	MAXSI_DECLARE_IMPLEMENTATION(MaxsiBufferStreamer, IBufferStreamer, MAXSI_INTERFACE_DYNAMIC);

public:
	MaxsiFileStreamer();
	MaxsiFileStreamer(IFileSystem* NewFileSystem, MaxsiHandle NewFileHandle);
	~MaxsiFileStreamer();

public:
	virtual int GetFlags() MAXSI_INTERFACE;
	virtual FileSize_t GetSize() MAXSI_INTERFACE;
	virtual MaxsiError SetSize(FileSize_t NewSize) MAXSI_INTERFACE;
	virtual FileSize_t GetPosition() MAXSI_INTERFACE;
	virtual MaxsiError Seek(FileSize_t Offset) MAXSI_INTERFACE;
	virtual MaxsiError Read(BYTE* Destination, size_t DestinationSize, size_t* ActualRead) MAXSI_INTERFACE;
	virtual MaxsiError ReadFrom(FileSize_t Offset, BYTE* Destination, size_t DestinationSize, size_t* ActualRead) MAXSI_INTERFACE;
	virtual MaxsiError Write(BYTE* Source, size_t SourceSize) MAXSI_INTERFACE;
	virtual MaxsiError WriteTo(FileSize_t Offset, BYTE* Source, size_t SourceSize) MAXSI_INTERFACE;
	virtual MaxsiError WriteFlush() MAXSI_INTERFACE;

public:
	IFileSystem* MyFileSystem;
	MaxsiHandle MyFileHandle;
	FileSize_t MyPosition;

};

//=============================================================================
//	Useful helper functions.
//=============================================================================
MAXSI_LINK IBufferStreamer* CreateBufferStreamer(BYTE* OriginalBuffer, size_t OriginalBufferSize);
MAXSI_LINK IBufferStreamer* CreateFileStreamer(MESTR* Path, IFileSystem* FileSystem = NULL);
MAXSI_LINK void DeleteStreamer(IBufferStreamer* BufferStreamer);

EndMaxsiNamespace

#endif

